﻿using ARC.Common.Help;
using Core.FrameWork.Commons;
using Core.FrameWork.Commons.ApiResult;
using Core.FrameWork.Commons.ApiResult.Model;
using Core.FrameWork.Commons.App;
using Core.FrameWork.Models;
using Core.FrameWork.Models.Models;
using Core.FrameWork.Models.Resp.System;
using IdentityModel;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

namespace Core.Web.Api.Utils
{
    /// <summary>
    /// Token令牌提供类
    /// </summary>
    public class TokenProvider
    {
        /// <summary>
        /// 获取HeaderToken
        /// </summary>
        /// <returns></returns>
        public CommonResult GetHeaderAuthorization()
        {
            CommonResult result = new CommonResult();

            var token = AppCenter.HttpContext.Request.Headers["Authorization"][0].ToString();
            if (string.IsNullOrEmpty(token))
            {
                result.Msg = ErrCode.err40004;
                result.Code = "40004";
                return result;
            }

            return ValidateToken(token);

        }
        /// <summary>
        /// 检查用户的Token有效性
        /// </summary>
        /// <param name="token">token令牌</param>
        /// <returns></returns>
        public CommonResult ValidateToken(string token)
        {
            try
            {
                if (!string.IsNullOrEmpty(token))
                    return ApiRespHelp.getError(ErrCode.err40004, ErrCode.err40004Msg);

                JwtSecurityToken jwtToken = new JwtSecurityTokenHandler().ReadJwtToken(token);
                if (jwtToken == null)
                    return ApiRespHelp.getError(ErrCode.err40004, ErrCode.err40004Msg);

                DateTime now = DateTime.UtcNow;
                DateTime refreshTime = jwtToken.ValidFrom;
                refreshTime = refreshTime.Add(TimeSpan.FromMinutes(APIConfig.JwtOption.refreshJwtTime));

                if (now > refreshTime && jwtToken.Issuer == APIConfig.JwtOption.Issuer)
                    return ApiRespHelp.getError(ErrCode.err40005, ErrCode.err40005Msg);

                if (jwtToken.Subject != GrantType.Password)
                    return ApiRespHelp.getError(ErrCode.err40004, ErrCode.err40004Msg);

                var claimlist = jwtToken?.Payload.Claims as List<Claim>;

                return ApiRespHelp.GetApiDataList(ErrCode.successCode, ErrCode.successMsg, claimlist);
            }
            catch (Exception ex)
            {
                //Log4NetHelper.Error("验证token异常", ex);
                throw new Exception(ErrCode.err40004Msg);
            }
        }
        /// <summary>
        /// 直接通过appid和加密字符串获取访问令牌接口
        /// </summary>
        /// <param name="granttype">获取access_token填写client_credential</param>
        /// <param name="appid">用户唯一凭证AppId</param>
        /// <param name="secret">用户唯一凭证密钥，即appsecret</param>
        /// <returns></returns>
        public TokenResult GenerateToken(string granttype, string appid, string secret)
        {
            var keyByteArray = Encoding.UTF8.GetBytes(secret);
            var signingKey = new SymmetricSecurityKey(keyByteArray);
            var expires = DateTime.UtcNow.Add(TimeSpan.FromMinutes(APIConfig.JwtOption.Expiration));
            var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256);
            var tokenDescripor = new SecurityTokenDescriptor
            {
                Subject = new ClaimsIdentity(new Claim[] {
                    new Claim(JwtClaimTypes.Audience,appid),
                    new Claim(JwtClaimTypes.Issuer,APIConfig.JwtOption.Issuer),
                    new Claim(JwtClaimTypes.Subject, GrantType.ClientCredentials)
                }, granttype),
                Expires = expires,
                //对称秘钥SymmetricSecurityKey
                //签名证书(秘钥，加密算法)SecurityAlgorithms
                SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(keyByteArray), SecurityAlgorithms.HmacSha256Signature)
            };
            var tokenHandler = new JwtSecurityTokenHandler();
            var token = tokenHandler.CreateToken(tokenDescripor);
            var tokenString = tokenHandler.WriteToken(token);
            TokenResult result = new TokenResult();
            result.AccessToken = tokenString;
            result.ExpiresIn = (int)TimeSpan.FromMinutes(APIConfig.JwtOption.Expiration).TotalMinutes;
            return result;
        }

        /// <summary>
        /// 根据用户获取token
        /// </summary>
        /// <param name="userInfo">用户信息</param>
        /// <param name="appid">应用Id</param>
        /// <returns></returns>
        public TokenResult LoginToken(RespAdminUser userInfo, string appid)
        {
            var tokenHandler = new JwtSecurityTokenHandler();
            var key = Encoding.UTF8.GetBytes(APIConfig.JwtOption.Secret);
            var authTime = DateTime.UtcNow;//授权时间
            var expires = authTime.Add(TimeSpan.FromMinutes(APIConfig.JwtOption.Expiration));//过期时间
            var tokenDescripor = new SecurityTokenDescriptor
            {
                Subject = new ClaimsIdentity(new Claim[] {
                    new Claim(JwtClaimTypes.Id, userInfo.Id.ToString()),
                    new Claim(JwtClaimTypes.Name, userInfo.TrueName),
                    new Claim(JwtClaimTypes.Role, string.Join(',',userInfo.RoleId)),
                    new Claim(JwtClaimTypes.Audience,appid),
                    new Claim(JwtClaimTypes.Issuer,APIConfig.JwtOption.Issuer),
                    new Claim(JwtClaimTypes.Subject, GrantType.Password)
                }),
                Expires = expires,
                //对称秘钥SymmetricSecurityKey
                //签名证书(秘钥，加密算法)SecurityAlgorithms
                SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
            };
            var token = tokenHandler.CreateToken(tokenDescripor);
            var tokenString = tokenHandler.WriteToken(token);
            TokenResult result = new TokenResult();
            result.AccessToken = tokenString;
            result.ExpiresIn = (int)TimeSpan.FromMinutes(APIConfig.JwtOption.Expiration).TotalMinutes;
            return result;
        }

        /// <summary>
        /// 根据登录用户获取token
        /// </summary>
        /// <param name="userInfo">用户信息</param>
        /// <param name="appid">应用Id</param>
        /// <returns></returns>
        public TokenResult GetUserToken(User userInfo, string appid)
        {
            var tokenHandler = new JwtSecurityTokenHandler();
            var key = Encoding.UTF8.GetBytes(APIConfig.JwtOption.Secret);
            var authTime = DateTime.UtcNow;//授权时间
            var expires = authTime.Add(TimeSpan.FromMinutes(APIConfig.JwtOption.Expiration));//过期时间
            var tokenDescripor = new SecurityTokenDescriptor
            {
                Subject = new ClaimsIdentity(new Claim[] {
                      new Claim(JwtClaimTypes.Id, userInfo.Id.ToString()),
                    new Claim(JwtClaimTypes.Name, userInfo.Account),
                    new Claim(JwtClaimTypes.Role, ""),
                    new Claim(JwtClaimTypes.Audience,appid),
                    new Claim(JwtClaimTypes.Issuer,APIConfig.JwtOption.Issuer),
                    new Claim(JwtClaimTypes.Subject, GrantType.Password)
                }),
                Expires = expires,
                //对称秘钥SymmetricSecurityKey
                //签名证书(秘钥，加密算法)SecurityAlgorithms
                SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
            };
            var token = tokenHandler.CreateToken(tokenDescripor);
            var tokenString = tokenHandler.WriteToken(token);
            TokenResult result = new TokenResult();
            result.AccessToken = tokenString;
            result.ExpiresIn = (int)TimeSpan.FromMinutes(APIConfig.JwtOption.Expiration).TotalMinutes;
            return result;
        }

        /// <summary>
        /// 获取过期Token
        /// </summary>
        /// <param name="userInfo">用户信息</param>
        /// <param name="appid">应用Id</param>
        /// <returns></returns>
        public TokenResult LoginTokenPast()
        {
            var tokenHandler = new JwtSecurityTokenHandler();
            var key = Encoding.UTF8.GetBytes(APIConfig.JwtOption.Secret);
            var authTime = DateTime.UtcNow;//授权时间
            var expires = authTime.Add(TimeSpan.FromMinutes(0));//过期时间
            var tokenDescripor = new SecurityTokenDescriptor
            {
                Subject = new ClaimsIdentity(new Claim[] {
                    new Claim(JwtClaimTypes.Issuer,APIConfig.JwtOption.Issuer),
                    new Claim(JwtClaimTypes.Subject, GrantType.Password)
                }),
                Expires = expires,
                //对称秘钥SymmetricSecurityKey
                //签名证书(秘钥，加密算法)SecurityAlgorithms
                SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
            };
            var token = tokenHandler.CreateToken(tokenDescripor);
            var tokenString = tokenHandler.WriteToken(token);
            TokenResult result = new TokenResult();
            result.AccessToken = tokenString;
            result.ExpiresIn = (int)TimeSpan.FromMinutes(APIConfig.JwtOption.Expiration).TotalMinutes;
            return result;
        }
    }
}
